#include <linux/proc_fs.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#include <linux/string.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqreturn.h>
#include <linux/module.h>
#include <linux/device.h>

#include "led_operation.h"

static int major;
static struct class *led_class;

struct led_operations *p_led_opr;


/*led args*/
//unsigned int led_gpio = 129;    //对照原理图  蜂鸣器
//unsigned int led_gpio = 19;     //对照原理图  按键
//unsigned int led_gpio = 3;        //对照原理图       led


static int led_open (struct inode *node, struct file *filp)
{
	int minor;
	minor = iminor(node);  /*获得次设备号*/
	
//	printk("led_open\n");
//	printk("%s %s %d\n",__FILE__, __FUNCTION__, __LINE__);

	/*根据次设备号初始化led*/
	p_led_opr->init(minor); 

	return 0;
}

static ssize_t led_read (struct file *filp, char *buf, size_t size, loff_t *offset)
{

	return 0;  
}

static ssize_t led_write (struct file *filp, const char *buf, size_t size, loff_t *offset)
{
	char status;
	int minor, err;
	
	/*根据次设备号和status控制led*/
	struct inode *inode = file_inode(filp);
	minor = iminor(inode);
	
	printk("led_drv_write\n");
	err = copy_from_user(&status, buf, 1);
	
	p_led_opr->ctl(minor, status);
	
	return 1;
}

static int led_release (struct inode *node, struct file *filp)
{
	printk("led_release\n");
	return 0;
}

/*1.定义 file_operations 结构体*/
static const struct file_operations led_fops = {
    .owner 		= THIS_MODULE,
	.read		= led_read,
	.write		= led_write,
	.open		= led_open,
	.release    = led_release,
};


/*3.入口函数*/
static int led_init(void)
{
	struct device *dev;
	int i;

	/************* 1.注册设备，返回设备号 ************/
	major = register_chrdev(0,"led_drv_board",&led_fops);

	/*2.在内核中创建设备*/
	led_class = class_create(THIS_MODULE, "led_class");
	if (IS_ERR(led_class)) {
		printk("led class create failed!\n");
	}

	/*获取 led_operations 对象*/
	p_led_opr = get_board_led_opr();

	/*3.在/dev下面创建设备节点*/
	//创建多个LED设备节点
	for(i=0; i<p_led_opr->num; i++)
	{
		printk("led%d device_create\n", i);
		dev = device_create(led_class, NULL, MKDEV(major, i), NULL, "led_drv_board_%d", i);
		if(IS_ERR(dev)) {
			printk("led device_create  failed!\n");
		}
	}

	return 0;
}

/*4.退出函数*/
static void led_exit(void)
{
	int i;

	//卸载设备
	unregister_chrdev(major,"led_fops");

	//销毁设备
	for(i=0; i<p_led_opr->num; i++)
		device_destroy(led_class, MKDEV(major, i));
	//删除设备类
	class_destroy(led_class);

	//删除io映射
	led_board_exit();
	
	printk("led_exit\n");

}	

module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");

